package com.example.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @auth shanyue
 * @date 2025年07月11日17:20
 */
public class MathUtil {

    //中文数字字符数组，0-9排序
    public static final String[] CN_NUM = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};

    //中文单位字符数组，对应个位、十位、百位
    public static final String[] CN_UNIT = {"", "拾", "佰", "仟"};

    //中文单位数组，对应万、亿、兆
    public static final String[] CN_SECTION_UNIT = {"", "万", "亿", "兆"};

    //中文数字到阿拉伯数字映射，方便中文数字解析
    public static final Map<Character, Integer> CN_TO_NUM = new HashMap<>();

    static {
        CN_TO_NUM.put('零', 0);
        CN_TO_NUM.put('壹', 1);
        CN_TO_NUM.put('贰', 2);
        CN_TO_NUM.put('叁', 3);
        CN_TO_NUM.put('肆', 4);
        CN_TO_NUM.put('伍', 5);
        CN_TO_NUM.put('陆', 6);
        CN_TO_NUM.put('柒', 7);
        CN_TO_NUM.put('捌', 8);
        CN_TO_NUM.put('玖', 9);
    }


    // 各单位对应平方米的换算率
    private static final BigDecimal MM2_TO_M2 = new BigDecimal("0.000001"); // 1 mm² = 0.000001 m²
    private static final BigDecimal CM2_TO_M2 = new BigDecimal("0.0001");   // 1 cm² = 0.0001 m²
    private static final BigDecimal DM2_TO_M2 = new BigDecimal("0.01");     // 1 dm² = 0.01 m²
    private static final BigDecimal M2_TO_M2 = BigDecimal.ONE;              // 1 m² = 1 m²
    private static final BigDecimal KM2_TO_M2 = new BigDecimal("1000000");  // 1 km² = 1,000,000 m²
    private static final BigDecimal MU_TO_M2 = new BigDecimal("666.6666667");// 1 亩 = 666.6666667 m²
    private static final BigDecimal HA_TO_M2 = new BigDecimal("10000");     // 1 公顷 = 10,000 m²
    private static final BigDecimal FT2_TO_M2 = new BigDecimal("0.09290304");// 1 平方英尺 = 0.09290304 m²
    private static final BigDecimal MI2_TO_M2 = new BigDecimal("2589988.110336"); // 1 平方英里 = 2,589,988.110336 m²
    private static final BigDecimal IN2_TO_M2 = new BigDecimal("0.00064516");    // 1 平方英寸 = 0.00064516 m²
    private static final BigDecimal AC_TO_M2 = new BigDecimal("4046.8564224");   // 1 英亩 = 4,046.8564224 m²

    public static BigDecimal toSquareMeter(String type, BigDecimal value) {
        return switch (type) {
            case "mm2" -> value.multiply(MM2_TO_M2);
            case "cm2" -> value.multiply(CM2_TO_M2);
            case "dm2" -> value.multiply(DM2_TO_M2);
            case "m2" -> value.multiply(M2_TO_M2);
            case "km2" -> value.multiply(KM2_TO_M2);
            case "mu" -> value.multiply(MU_TO_M2);
            case "ha" -> value.multiply(HA_TO_M2);
            case "ft2" -> value.multiply(FT2_TO_M2);
            case "mi2" -> value.multiply(MI2_TO_M2);
            case "in2" -> value.multiply(IN2_TO_M2);
            case "ac" -> value.multiply(AC_TO_M2);
            default -> throw new IllegalArgumentException("未知面积单位：" + type);
        };
    }

    public static BigDecimal fromSquareMeter(String type, BigDecimal m2Value) {
        return switch (type) {
            case "mm2" -> m2Value.divide(MM2_TO_M2, 10, RoundingMode.HALF_UP);
            case "cm2" -> m2Value.divide(CM2_TO_M2, 10, RoundingMode.HALF_UP);
            case "dm2" -> m2Value.divide(DM2_TO_M2, 10, RoundingMode.HALF_UP);
            case "m2" -> m2Value;
            case "km2" -> m2Value.divide(KM2_TO_M2, 10, RoundingMode.HALF_UP);
            case "mu" -> m2Value.divide(MU_TO_M2, 10, RoundingMode.HALF_UP);
            case "ha" -> m2Value.divide(HA_TO_M2, 10, RoundingMode.HALF_UP);
            case "ft2" -> m2Value.divide(FT2_TO_M2, 10, RoundingMode.HALF_UP);
            case "mi2" -> m2Value.divide(MI2_TO_M2, 10, RoundingMode.HALF_UP);
            case "in2" -> m2Value.divide(IN2_TO_M2, 10, RoundingMode.HALF_UP);
            case "ac" -> m2Value.divide(AC_TO_M2, 10, RoundingMode.HALF_UP);
            default -> throw new IllegalArgumentException("未知面积单位：" + type);
        };
    }

    // 单位换算表（单位 -> 相对字节(B)的倍数）
    public static final Map<String, BigDecimal> BYTE_UNIT_TO_BYTE = new LinkedHashMap<>();
    public static final Map<String, String> BYTE_UNIT_LABELS = new LinkedHashMap<>();

    static {
        // 使用 1024 为换算基准
        BYTE_UNIT_TO_BYTE.put("b", new BigDecimal("1").divide(new BigDecimal("8"), 20, RoundingMode.HALF_UP));
        BYTE_UNIT_TO_BYTE.put("Kb", new BigDecimal("1024").divide(new BigDecimal("8"), 20, RoundingMode.HALF_UP));
        BYTE_UNIT_TO_BYTE.put("Mb", new BigDecimal("1024").pow(2).divide(new BigDecimal("8"), 20, RoundingMode.HALF_UP));
        BYTE_UNIT_TO_BYTE.put("Gb", new BigDecimal("1024").pow(3).divide(new BigDecimal("8"), 20, RoundingMode.HALF_UP));
        BYTE_UNIT_TO_BYTE.put("Tb", new BigDecimal("1024").pow(4).divide(new BigDecimal("8"), 20, RoundingMode.HALF_UP));

        BYTE_UNIT_TO_BYTE.put("B", BigDecimal.ONE);
        BYTE_UNIT_TO_BYTE.put("KB", new BigDecimal("1024"));
        BYTE_UNIT_TO_BYTE.put("MB", new BigDecimal("1024").pow(2));
        BYTE_UNIT_TO_BYTE.put("GB", new BigDecimal("1024").pow(3));
        BYTE_UNIT_TO_BYTE.put("TB", new BigDecimal("1024").pow(4));

        BYTE_UNIT_LABELS.put("b", "比特 (b)");
        BYTE_UNIT_LABELS.put("Kb", "千比特 (Kb)");
        BYTE_UNIT_LABELS.put("Mb", "兆比特 (Mb)");
        BYTE_UNIT_LABELS.put("Gb", "千兆比特 (Gb)");
        BYTE_UNIT_LABELS.put("Tb", "太比特 (Tb)");
        BYTE_UNIT_LABELS.put("B", "字节 (B)");
        BYTE_UNIT_LABELS.put("KB", "千字节 (KB)");
        BYTE_UNIT_LABELS.put("MB", "兆字节 (MB)");
        BYTE_UNIT_LABELS.put("GB", "千兆字节 (GB)");
        BYTE_UNIT_LABELS.put("TB", "太字节 (TB)");
    }

    // 单位到米的换算比例
    public static final Map<String, BigDecimal> LENGTH_UNIT_TO_METER = Map.of(
            "mm", new BigDecimal("0.001"),
            "cm", new BigDecimal("0.01"),
            "dm", new BigDecimal("0.1"),
            "m", new BigDecimal("1"),
            "in", new BigDecimal("0.0254"),
            "ft", new BigDecimal("0.3048"),
            "mi", new BigDecimal("1609.344")
    );

    public static final Map<String, String> LENGTH_UNIT_LABELS = Map.of(
            "mm", "毫米 (mm)",
            "cm", "厘米 (cm)",
            "dm", "分米 (dm)",
            "m", "米 (m)",
            "in", "英寸 (in)",
            "ft", "英尺 (ft)",
            "mi", "英里 (mi)"
    );

    // 单位换算因子（单位 -> 相对千克的换算比例）
    public static final Map<String, BigDecimal> QUALITY_UNIT_TO_KG = Map.of(
            "mcg", new BigDecimal("0.000000001"),
            "mg", new BigDecimal("0.000001"),
            "g", new BigDecimal("0.001"),
            "kg", BigDecimal.ONE,
            "jin", new BigDecimal("0.5"),
            "oz", new BigDecimal("0.0283495231"),
            "lb", new BigDecimal("0.45359237"),
            "mt", new BigDecimal("1000"),
            "t", new BigDecimal("1000")
    );

    // 单位对应的显示标签
    public static final Map<String, String> QUALITY_UNIT_LABELS = Map.of(
            "mcg", "微克 (mcg)",
            "mg", "毫克 (mg)",
            "g", "克 (g)",
            "kg", "千克 (kg)",
            "jin", "斤 (jin)",
            "lb", "磅 (lb)",
            "oz", "盎司 (oz)",
            "mt", "公吨 (mt)",
            "t", "吨 (t)"
    );

    // 单位到秒的换算比例
    public static final Map<String, BigDecimal> TIME_UNIT_TO_SECOND = Map.of(
            "ns", new BigDecimal("0.000000001"),          // 纳秒
            "μs", new BigDecimal("0.000001"),             // 微秒
            "ms", new BigDecimal("0.001"),                // 毫秒
            "s", BigDecimal.ONE,                          // 秒
            "min", new BigDecimal("60"),                  // 分钟
            "h", new BigDecimal("3600"),                  // 小时
            "d", new BigDecimal("86400"),                  // 天
            "week", new BigDecimal("604800"),              // 周
            "month", new BigDecimal("2592000"),            // 月（按30天计）
            "year", new BigDecimal("31536000")             // 年（按365天计）
    );

    // 单位对应标签
    public static final Map<String, String> TIME_UNIT_LABELS = Map.of(
            "ns", "纳秒 (ns)",
            "μs", "微秒 (μs)",
            "ms", "毫秒 (ms)",
            "s", "秒 (s)",
            "min", "分钟 (min)",
            "h", "小时 (h)",
            "d", "天 (d)",
            "week", "周 (week)",
            "month", "月 (month)",
            "year", "年 (year)"
    );

}
